home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Mac Game Programming Gurus
/
TricksOfTheMacGameProgrammingGurus.iso
/
More Source
/
Libraries
/
SpriteEngine
/
SpriteEngine.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-14
|
5KB
|
200 lines
#include "SpriteTools.h"
/*
SpriteEngine
============
This demo sprite engine is designed for the following structure:
(Lower units use the higher ones.)
SpriteTools.c: Utilities for loading and drawing
|
SpriteHanders.c: All custom code: Sprite init, movement, collisions
|
SpriteEngine.c: Main program, sprite engine
The only files you need to edit in order to change the sprite behavior are
the files SpriteHandlers.c and SpriteHandlers.h.
*/
/* The actual sprite engine */
static void InitSpriteEngine(Rect *offBounds, short backgroundPictureID)
{
PicHandle backgroundPicture;
GDHandle saveGD;
GWorldPtr savePort;
MyNewGWorld(&gOffScreen, offBounds);
MyNewGWorld(&gBackScreen, offBounds);
GetGWorld(&savePort, &saveGD); /*Save the port/device*/
SetGWorld((GWorldPtr)gBackScreen, nil);
EraseRect(offBounds);
backgroundPicture = GetPicture(backgroundPictureID);
if (backgroundPicture != nil)
{
DrawPicture(backgroundPicture, offBounds);
ReleaseResource((Handle)backgroundPicture);
}
SetGWorld((GWorldPtr)gOffScreen, nil);
CopyBits(&gBackScreen->portBits, &gOffScreen->portBits, offBounds, offBounds, srcCopy, nil);
SetGWorld((GWorldPtr)myWindow, GetMainDevice());
CopyBits(&gOffScreen->portBits, &myWindow->portBits, offBounds, offBounds, srcCopy, nil);
SetGWorld(savePort, saveGD);
} /*InitSpriteEngine*/
static void RunSpriteEngine()
{
#define kWallBounce 7 /*1/10-ths of speed kept after wallbounce*/
#define kBallDiameterSquared (32*32) /*Diameter 32, squared*/
Rect tmpRect;
GDHandle saveGD;
GWorldPtr savePort;
SpritePtr theSprite, anotherSprite;
Rect bounds1, bounds2;
GetGWorld(&savePort, &saveGD); /*Save the port/device*/
/*1: Erase all sprites from gOffScreen*/
/*Note: We keep the rectangles for erasing on the screen, later.*/
SetGWorld((GWorldPtr)gOffScreen, nil);
theSprite = gSpriteList;
while (theSprite != nil)
{
theSprite->drawingRect = theSprite->face->portRect;
OffsetRect(&theSprite->drawingRect, theSprite->position.h, theSprite->position.v);
CopyBits(&gBackScreen->portBits, &gOffScreen->portBits, &theSprite->drawingRect, &theSprite->drawingRect, srcCopy, nil);
theSprite = theSprite->next;
}
/*2: Change the position and speed*/
theSprite = gSpriteList;
while (theSprite != nil)
{
MoveSprite(theSprite);
theSprite = theSprite->next;
}/*position/speed loop*/
/*3: Check for collisions*/
theSprite = gSpriteList;
while (theSprite != nil) /*For all sprites in the list…*/
{
bounds1 = theSprite->face->portRect;
OffsetRect(&bounds1, theSprite->position.h, theSprite->position.v);
anotherSprite = theSprite->next;
while (anotherSprite != nil)
{
/*compare its position to all following sprites*/
bounds2 = anotherSprite->face->portRect;
OffsetRect(&bounds2, anotherSprite->position.h, anotherSprite->position.v);
if (SectRect(&bounds1, &bounds2, &tmpRect))
HitSprite(theSprite, anotherSprite);
anotherSprite = anotherSprite->next;
}
theSprite = theSprite->next;
} /*collision loop*/
/*4: Draw sprites in gOffScreen*/
/*Note: PlotCIcon or DrawPicture are not very fast! We can speed it up my*/
/*pre-drawing them in some offscreen, and CopyBits them from there.*/
theSprite = gSpriteList;
while (theSprite != nil) /*For all sprites in the list…*/
{
tmpRect = theSprite->face->portRect;
OffsetRect(&tmpRect, theSprite->position.h, theSprite->position.v);
PlotFace(theSprite->face, gOffScreen, *(Point *)&tmpRect);
theSprite = theSprite->next;
}
/*5: Copy sprites to the screen (gWind) - both old and new position!*/
/*Note: Depending on what limitations we have on movement, we may be able to avoid the multiple*/
/*CopyBitsing here. E.g. if sprites always move a maximum of 2 pixels, we can copy a 2 pixels*/
/*larger area, etc.*/
SetGWorld((GWorldPtr)myWindow, saveGD); /*Vilken GD???*/
theSprite = gSpriteList;
while (theSprite != nil) /*For all sprites in the list…*/
{
CopyBits(&gOffScreen->portBits, &myWindow->portBits, &theSprite->drawingRect, &theSprite->drawingRect, srcCopy, nil);
theSprite->drawingRect = theSprite->face->portRect;
OffsetRect(&theSprite->drawingRect, theSprite->position.h, theSprite->position.v);
CopyBits(&gOffScreen->portBits, &myWindow->portBits, &theSprite->drawingRect, &theSprite->drawingRect, srcCopy, nil);
theSprite = theSprite->next;
}
SetGWorld(savePort, saveGD);
}; /*RunSpriteEngine*/
/* Standard inits */
static void InitToolbox(void) {
InitGraf (&qd.thePort);
InitFonts ();
FlushEvents (everyEvent,0);
InitWindows ();
InitMenus ();
TEInit ();
InitDialogs (nil);
InitCursor ();
} /*InitToolbox*/
/* Initialize - create window, load graphics */
static void InitStuff()
{
Rect windowRectangle;
/*Set up the window*/
SetRect(&windowRectangle, 50, 50, 450, 350);
myWindow = NewCWindow(nil, &windowRectangle, "\pSprite test", true, documentProc, (WindowPtr)-1L, false, 0);
SetPort(myWindow);
qd.randSeed = TickCount (); /*Seed the random number generator*/
} /*InitStuff*/
#define kBackgroundPictureID 128
/* Main program */
void main(void)
{
long startTime;
InitToolbox();
InitStuff();
InitSpriteEngine(&myWindow->portRect, kBackgroundPictureID);
InitSprites();
HideCursor();
while (!Button())
{
startTime = TickCount();
RunSpriteEngine();
while (TickCount() < startTime + kFrameTime);
}
ShowCursor();
FlushEvents(mDownMask, 0);
} /*main*/